#include"SecIslSNMGR.hpp"
#include"MapApp.hpp"
#include"../Base/Concurrency/Lock.hpp"
#include<filesystem>
#include<fstream>
#include"rapidjson/document.h"
#include"SatelliteMGR.hpp"


namespace SC_SUN
{
    namespace Details {

        bool LoadEvSecIslSNDataSub(const std::string& path, EvSecIslSNDataSub& data)
        {
            using namespace rapidjson;

            int fileLen = std::filesystem::file_size(path);
            std::string buff;
            buff.resize(fileLen);
            FILE* pf = fopen(path.data(), "rb");
            fread(buff.data(), 1, fileLen, pf);
            fclose(pf);

            Document doc;
            doc.Parse(buff.data());
            auto obj = doc.GetObj();

            data.SEC_SN = obj["Picture_Info"].GetObj()["SEC_SN"].GetString();
            data.SEC_ST = obj["Picture_Info"].GetObj()["SEC_ST"].GetDouble();
            data.SEC_NUM = obj["Picture_Info"].GetObj()["SEC_NUM"].GetUint64();
            data.SEC_ISL_SN = obj["SEC_ISL_SN"].GetString();
            data.SEC_ISL_SAT1 = obj["SEC_ISL_SAT1"].GetString();
            data.SEC_ISL_SAT2 = obj["SEC_ISL_SAT2"].GetString();

            data.SEC_ISL_TSAT_POS_HF[0] = obj["SEC_ISL_TSAT_POS_HF"].GetArray()[0].GetDouble();
            data.SEC_ISL_TSAT_POS_HF[1] = obj["SEC_ISL_TSAT_POS_HF"].GetArray()[1].GetDouble();
            data.SEC_ISL_TSAT_POS_HF[2] = obj["SEC_ISL_TSAT_POS_HF"].GetArray()[2].GetDouble();

            data.SEC_ISL_TSAT_VEL_HF[0] = obj["SEC_ISL_TSAT_VEL_HF"].GetArray()[0].GetDouble();
            data.SEC_ISL_TSAT_VEL_HF[1] = obj["SEC_ISL_TSAT_VEL_HF"].GetArray()[1].GetDouble();
            data.SEC_ISL_TSAT_VEL_HF[2] = obj["SEC_ISL_TSAT_VEL_HF"].GetArray()[2].GetDouble();

            data.SEC_ISL_RSAT_POS_HF[0] = obj["SEC_ISL_RSAT_POS_HF"].GetArray()[0].GetDouble();
            data.SEC_ISL_RSAT_POS_HF[1] = obj["SEC_ISL_RSAT_POS_HF"].GetArray()[1].GetDouble();
            data.SEC_ISL_RSAT_POS_HF[2] = obj["SEC_ISL_RSAT_POS_HF"].GetArray()[2].GetDouble();

            data.SEC_ISL_RSAT_VEL_HF[0] = obj["SEC_ISL_RSAT_VEL_HF"].GetArray()[0].GetDouble();
            data.SEC_ISL_RSAT_VEL_HF[1] = obj["SEC_ISL_RSAT_VEL_HF"].GetArray()[1].GetDouble();
            data.SEC_ISL_RSAT_VEL_HF[2] = obj["SEC_ISL_RSAT_VEL_HF"].GetArray()[2].GetDouble();

            data.SEC_ISL_TSAT_POS_MS[0] = obj["SEC_ISL_TSAT_POS_MS"].GetArray()[0].GetDouble();
            data.SEC_ISL_TSAT_POS_MS[1] = obj["SEC_ISL_TSAT_POS_MS"].GetArray()[1].GetDouble();
            data.SEC_ISL_TSAT_POS_MS[2] = obj["SEC_ISL_TSAT_POS_MS"].GetArray()[2].GetDouble();

            data.SEC_ISL_TSAT_VEL_MS[0] = obj["SEC_ISL_TSAT_VEL_MS"].GetArray()[0].GetDouble();
            data.SEC_ISL_TSAT_VEL_MS[1] = obj["SEC_ISL_TSAT_VEL_MS"].GetArray()[1].GetDouble();
            data.SEC_ISL_TSAT_VEL_MS[2] = obj["SEC_ISL_TSAT_VEL_MS"].GetArray()[2].GetDouble();

            data.SEC_ISL_RSAT_POS_MS[0] = obj["SEC_ISL_RSAT_POS_MS"].GetArray()[0].GetDouble();
            data.SEC_ISL_RSAT_POS_MS[1] = obj["SEC_ISL_RSAT_POS_MS"].GetArray()[1].GetDouble();
            data.SEC_ISL_RSAT_POS_MS[2] = obj["SEC_ISL_RSAT_POS_MS"].GetArray()[2].GetDouble();

            data.SEC_ISL_RSAT_VEL_MS[0] = obj["SEC_ISL_RSAT_VEL_MS"].GetArray()[0].GetDouble();
            data.SEC_ISL_RSAT_VEL_MS[1] = obj["SEC_ISL_RSAT_VEL_MS"].GetArray()[1].GetDouble();
            data.SEC_ISL_RSAT_VEL_MS[2] = obj["SEC_ISL_RSAT_VEL_MS"].GetArray()[2].GetDouble();

            data.SEC_ISL_CLER = obj["SEC_ISL_CLER"].GetDouble();

            data.SEC_ISL_RPS_HF[0] = obj["SEC_ISL_RPS_HF"].GetArray()[0].GetDouble();
            data.SEC_ISL_RPS_HF[1] = obj["SEC_ISL_RPS_HF"].GetArray()[1].GetDouble();
            data.SEC_ISL_RPS_HF[2] = obj["SEC_ISL_RPS_HF"].GetArray()[2].GetDouble();
            
            data.SEC_ISL_RVL_HF[0] = obj["SEC_ISL_RVL_HF"].GetArray()[0].GetDouble();
            data.SEC_ISL_RVL_HF[1] = obj["SEC_ISL_RVL_HF"].GetArray()[1].GetDouble();
            data.SEC_ISL_RVL_HF[2] = obj["SEC_ISL_RVL_HF"].GetArray()[2].GetDouble();

            data.SEC_ISL_RPS_ER[0] = obj["SEC_ISL_RPS_ER"].GetArray()[0].GetDouble();
            data.SEC_ISL_RPS_ER[1] = obj["SEC_ISL_RPS_ER"].GetArray()[1].GetDouble();
            data.SEC_ISL_RPS_ER[2] = obj["SEC_ISL_RPS_ER"].GetArray()[2].GetDouble();

            data.SEC_ISL_RVL_ER[0] = obj["SEC_ISL_RVL_ER"].GetArray()[0].GetDouble();
            data.SEC_ISL_RVL_ER[1] = obj["SEC_ISL_RVL_ER"].GetArray()[1].GetDouble();
            data.SEC_ISL_RVL_ER[2] = obj["SEC_ISL_RVL_ER"].GetArray()[2].GetDouble();

            data.SEC_ISL_RVL_HD = obj["SEC_ISL_RVL_HD"].GetDouble();
            data.SEC_ISL_TL = obj["SEC_ISL_TL"].GetDouble();
            data.EAR_APD = obj["EAR_APD"].GetDouble();
            data.EAR_NED = obj["EAR_NED"].GetDouble();
            data.EAR_NER = obj["EAR_NER"].GetDouble();

            data.SEC_ISL_MWR_HF = obj["SEC_ISL_MWR_HF"].GetDouble();
            data.SEC_ISL_MWV_HF = obj["SEC_ISL_MWV_HF"].GetDouble();
            data.SEC_ISL_MWA_HF = obj["SEC_ISL_MWA_HF"].GetDouble();
            data.SEC_ISL_MWT_HF = obj["SEC_ISL_MWT_HF"].GetDouble();
            data.SEC_ISL_MWR_ER = obj["SEC_ISL_MWR_ER"].GetDouble();
            data.SEC_ISL_MWV_ER = obj["SEC_ISL_MWV_ER"].GetDouble();
            data.SEC_ISL_MWA_ER = obj["SEC_ISL_MWA_ER"].GetDouble();
            data.SEC_ISL_MWT_ER = obj["SEC_ISL_MWT_ER"].GetDouble();

            data.SEC_ISL_LSR_HF = obj["SEC_ISL_LSR_HF"].GetDouble();
            data.SEC_ISL_LSV_HF = obj["SEC_ISL_LSV_HF"].GetDouble();
            data.SEC_ISL_LSA_HF = obj["SEC_ISL_LSA_HF"].GetDouble();
            data.SEC_ISL_LST_HF = obj["SEC_ISL_LST_HF"].GetDouble();
            data.SEC_ISL_LSR_ER = obj["SEC_ISL_LSR_ER"].GetDouble();
            data.SEC_ISL_LSV_ER = obj["SEC_ISL_LSV_ER"].GetDouble();
            data.SEC_ISL_LSA_ER = obj["SEC_ISL_LSA_ER"].GetDouble();
            data.SEC_ISL_LST_ER = obj["SEC_ISL_LST_ER"].GetDouble();

            return true;
        }
    }


    int SecIslSNManGR::LoadData()
    {
        using namespace rapidjson;

        mSeclslSNs.clear();
        mSatToSeclslSNs.clear();
        mAllSliceInfos.clear();

        int num = 0;

        //读取配置文件目录
        std::string path = mApp.CurScene() + "/Data_Summary/SEC_Info.json";

        //读取字符串数据
        int fileLen = std::filesystem::file_size(path);
        std::string data;
        data.resize(fileLen);
        FILE* pf = fopen(path.data(), "rb");
        fread(data.data(), 1, fileLen, pf);
        fclose(pf);

        //解析json数据
        mInfos.Parse(data.data());
        auto obj = mInfos.GetObj();

        //解析星间汇总信息
        double ST_TT = obj["ST_TT"].GetDouble();
        double SEC_STP = obj["SEC_STP"].GetDouble();
        uint64_t SEC_NUM = obj["SEC_NUM"].GetUint64();

        //保存各切片星间数据
        auto array = obj["Slice_Info"].GetArray();
        for (int i = 0; i < array.Size(); i++)
        {
            mAllSliceInfos.push_back(array[i].GetObj());
        }

        //解析切片0的数据
        auto obj2 = mAllSliceInfos[0];
        auto array2 = obj2["SEC_ISL_Info"].GetArray();

        std::string SEC_SN = obj2["SEC_SN"].GetString();
        double SEC_ST = obj2["SEC_ST"].GetDouble();
        uint64_t SEC_ISL_NUM = obj2["SEC_ISL_NUM"].GetUint64(); 
        std::string PATH_SEC_SN = obj2["SEC_path"].GetString();

        mApp.GetSatelliteMGR().ClearAllCollections();
        for (int i = 0; i < array2.Size(); i++)
        {
            auto pSecIsn = std::make_shared<EvSecIslSNData>();
            EvSecIslSNData& secIsn = *pSecIsn;

            secIsn.ST_TT = ST_TT;
            secIsn.SEC_STP = SEC_STP;
            secIsn.SEC_NUM = SEC_NUM;
            secIsn.SEC_SN = SEC_SN;
            secIsn.SEC_ST = SEC_ST;
            secIsn.SEC_ISL_NUM = SEC_ISL_NUM;
            secIsn.PATH_SEC_SN = PATH_SEC_SN;

            secIsn.SEC_ISL_SN = array2[i].GetObj()["SEC_ISL_SN"].GetString();
            secIsn.SEC_ISL_SAT1 = array2[i].GetObj()["SEC_ISL_SAT1"].GetString();
            secIsn.SEC_ISL_SAT2 = array2[i].GetObj()["SEC_ISL_SAT2"].GetString();
            secIsn.PATH_SEC_ISL_SN = array2[i].GetObj()["SEC_ISL_path"].GetString();

            //给卫星添加子父节点
            mApp.GetSatelliteMGR().AddChild(secIsn.SEC_ISL_SAT1, secIsn.SEC_ISL_SAT2);
            mApp.GetSatelliteMGR().AddParent(secIsn.SEC_ISL_SAT2, secIsn.SEC_ISL_SAT1);

            ////加载星间数据
            ////由于路径问题需要去掉一部分
            //std::string path = mApp.CurScene();
            //int idx = path.find_last_of('/');
            //path = path.substr(0, idx + 1);
            //Details::LoadEvSecIslSNDataSub(path + secIsn.PATH_SEC_ISL_SN, secIsn.SEC_ISL_SN_SUB);

            Add(secIsn.SEC_ISL_SN, pSecIsn);

            mMutex.Lock();
            mSatToSeclslSNs.insert({secIsn.SEC_ISL_SAT1 + secIsn.SEC_ISL_SAT2, pSecIsn});
            mMutex.Unlock();

            num++;
        }


        return num;
    }


    int SecIslSNManGR::LoadBySlice(uint32_t slice)
    {
        using namespace rapidjson;

        int num = 0;

        if (slice >= mAllSliceInfos.size())
            return num;

        auto obj2 = mAllSliceInfos[slice];
        auto array2 = obj2["SEC_ISL_Info"].GetArray();

        std::string SEC_SN = obj2["SEC_SN"].GetString();
        double SEC_ST = obj2["SEC_ST"].GetDouble();
        uint64_t SEC_ISL_NUM = obj2["SEC_ISL_NUM"].GetUint64(); 
        std::string PATH_SEC_SN = obj2["SEC_path"].GetString();

        mApp.GetSatelliteMGR().ClearAllCollections();
        for (int i = 0; i < array2.Size(); i++)
        {
            auto pSecIsn = std::make_shared<EvSecIslSNData>();
            EvSecIslSNData& secIsn = *pSecIsn;

            secIsn.SEC_ISL_SN = array2[i].GetObj()["SEC_ISL_SN"].GetString();
            secIsn.SEC_ISL_SAT1 = array2[i].GetObj()["SEC_ISL_SAT1"].GetString();
            secIsn.SEC_ISL_SAT2 = array2[i].GetObj()["SEC_ISL_SAT2"].GetString();
            secIsn.PATH_SEC_ISL_SN = array2[i].GetObj()["SEC_ISL_path"].GetString();

            //给卫星添加子父节点
            mApp.GetSatelliteMGR().AddChild(secIsn.SEC_ISL_SAT1, secIsn.SEC_ISL_SAT2);
            mApp.GetSatelliteMGR().AddParent(secIsn.SEC_ISL_SAT2, secIsn.SEC_ISL_SAT1);

            ////加载星间数据
            ////由于路径问题需要去掉一部分
            //std::string path = mApp.CurScene();
            //int idx = path.find_last_of('/');
            //path = path.substr(0, idx + 1);
            //Details::LoadEvSecIslSNDataSub(path + secIsn.PATH_SEC_ISL_SN, secIsn.SEC_ISL_SN_SUB);

            Add(secIsn.SEC_ISL_SN, pSecIsn);

            mMutex.Lock();
            mSatToSeclslSNs.insert({secIsn.SEC_ISL_SAT1 + secIsn.SEC_ISL_SAT2, pSecIsn});
            mMutex.Unlock();

            num++;
        }

        return num;
    }


    bool SecIslSNManGR::Add(const std::string& SEC_ISL_SN, const std::shared_ptr<EvSecIslSNData>& sat)
    {
        MMF::LockGuard lk(mMutex);

        //不存在就开始添加
        if (mSeclslSNs.find(SEC_ISL_SN) == mSeclslSNs.end())
        {
            mSeclslSNs.insert({SEC_ISL_SN, sat});
            return true;
        }

        return false;
    }


    bool SecIslSNManGR::Find(const std::string& SEC_ISL_SN)
    {
        MMF::LockGuard lk(mMutex);
        return mSeclslSNs.find(SEC_ISL_SN) != mSeclslSNs.end();
    }

    
    EvSecIslSNData* SecIslSNManGR::Get(const std::string& SEC_ISL_SN)
    {
        MMF::LockGuard lk(mMutex);

        //不存在就开始添加
        std::unordered_map<std::string, std::shared_ptr<EvSecIslSNData>>::iterator it = mSeclslSNs.find(SEC_ISL_SN);
        if (it != mSeclslSNs.end())
        {
            //加载星间数据
            std::string path = mApp.CurScene();
            int idx = path.find_last_of('/');
            path = path.substr(0, idx + 1);
            Details::LoadEvSecIslSNDataSub(path + it->second->PATH_SEC_ISL_SN, it->second->SEC_ISL_SN_SUB);

            return it->second.get();
        }
        return nullptr;
    }


    EvSecIslSNData* SecIslSNManGR::GetBySatellite(const std::string& SEC_ISL_SAT1, const std::string& SEC_ISL_SAT2)
    {
        MMF::LockGuard lk(mMutex);

        //不存在就开始添加
        std::unordered_map<std::string, std::shared_ptr<EvSecIslSNData>>::iterator it = mSatToSeclslSNs.find(SEC_ISL_SAT1 + SEC_ISL_SAT2);
        if (it != mSatToSeclslSNs.end())
        {
            //加载星间数据
            std::string path = mApp.CurScene();
            int idx = path.find_last_of('/');
            path = path.substr(0, idx + 1);
            Details::LoadEvSecIslSNDataSub(path + it->second->PATH_SEC_ISL_SN, it->second->SEC_ISL_SN_SUB);

            return it->second.get();
        }
        return nullptr;
    }

    
    bool SecIslSNManGR::Delete(const std::string& SEC_ISL_SN)
    {
         MMF::LockGuard lk(mMutex);

        //不存在就开始添加
        std::unordered_map<std::string, std::shared_ptr<EvSecIslSNData>>::iterator it = mSeclslSNs.find(SEC_ISL_SN);
        if (it != mSeclslSNs.end())
        {
            mSeclslSNs.erase(it);
            return true;
        }
        return false;
    }

    
    bool SecIslSNManGR::Update(const std::string& SEC_ISL_SN, const std::shared_ptr<EvSecIslSNData>& sat)
    {
          MMF::LockGuard lk(mMutex);

        //不存在就开始添加
        std::unordered_map<std::string, std::shared_ptr<EvSecIslSNData>>::iterator it = mSeclslSNs.find(SEC_ISL_SN);
        if (it != mSeclslSNs.end())
        {
            it->second = sat;
            return true;
        }
        return false;
    }


    void SecIslSNManGR::GetTimeAndStep(double& time, double& step)
    {
        time = mSeclslSNs.begin()->second->ST_TT;
        step = mSeclslSNs.begin()->second->SEC_STP;
    }


}